package com.zz.common.service

import akka.actor.ActorSystem
import cats.effect._
import cats.implicits._
import com.zz.common.{AppConfig, GlobalContext}
import com.zz.common.api.ApiService
//import com.zz.dsp.database.DatabaseComponentF
import com.typesafe.scalalogging.Logger
import org.http4s.HttpRoutes
import org.http4s.implicits._
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder

abstract class HttpServer[F[_]]()(implicit system: ActorSystem) {

  protected val logger: Logger = Logger(getClass)

  def routes(): HttpRoutes[F]

//  def routes(): HttpRoutes[F]
  def serve(config: AppConfig.HttpConfig)(implicit ef: ConcurrentEffect[F], timer: Timer[F]): F[ExitCode] = {
//  def serve(config: AppConfig.HttpConfig)(implicit ef: ConcurrentEffect[F], timer: Timer[F], dc: DatabaseComponentF[F]): F[ExitCode] = {
    val server: F[Unit] = BlazeServerBuilder[F]
      .bindHttp(config.port, config.host)
      .withHttpApp(Router("/" -> routes).orNotFound)
      .serve
      .compile
      .drain
    for {
      _ <- printAsciiBanner
      _ <- server
    } yield ExitCode.Success
  }

  def printAsciiBanner(implicit ef: ConcurrentEffect[F]): F[Unit] =
    Resource
      .fromAutoCloseable(ef.delay(scala.io.Source.fromResource("issue.txt")))
      .use { x =>
        ef.delay(Logger("com.zz.dsp.mapping.Main.Logo").info(x.mkString))
      }
}

//object HttpServerIO extends HttpServer[IO] {
//
////  def routes()(implicit dc: DatabaseComponentF[IO]): HttpRoutes[IO] = (new ApiServiceIO).routes
////def routes()(implicit ctx: GlobalContext[IO]): HttpRoutes[IO] = (new ApiServiceIO).routes
//
//  override def routes()(implicit ctx: GlobalContext[IO]): HttpRoutes[IO] = (new ApiServiceIO).routes
//}

object HttpServer {
  def apply[F[_]: ConcurrentEffect: Timer]()(implicit system: ActorSystem): HttpServer[F] = new HttpServer[F] {
    override def routes(): HttpRoutes[F] = ApiService[F].routes
  }
}